package com.xbongbong.paas.service.workflow.setting.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.enums.WorkflowTriggerMethodEnum;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.clazz.ConditionClass;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.ConditionListHelp;
import com.xbongbong.paas.help.WorkflowNodeHelp;
import com.xbongbong.paas.pojo.workflow.NodeCoreConfigurationPojo;
import com.xbongbong.paas.pojo.workflow.WorkflowNodeTreePojo;
import com.xbongbong.paas.pojo.workflow.nodes.WorkflowConditionContentFilterPojo;
import com.xbongbong.paas.pojo.workflow.nodes.WorkflowConditionContentFiltersPojo;
import com.xbongbong.paas.pojo.workflow.nodes.vo.ConditionNodeVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowConditionFilterPojoVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowConditionFiltersPojoVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowConditionPojoVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeGetVO;
import com.xbongbong.paas.pojo.workflow.settings.ConditionTypeEnum;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowGetPojo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowNodeConditionTypeEnum;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowEnableVO;
import com.xbongbong.paas.service.workflow.setting.AbstractWorkflowNodeSettings;
import com.xbongbong.paas.service.workflow.setting.ConditionNodeFieldService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.util.WorkflowNodeUtil;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowNodeEntityExt;
import com.xbongbong.workflow.enums.WorkflowConditionOperatorEnum;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.pojo.nodes.ConditionNode;
import com.xbongbong.workflow.pojo.nodes.WorkflowConditionFilters;
import com.xbongbong.workflow.pojo.nodes.WorkflowConditionPojo;
import com.xbongbong.workflow.pojo.nodes.WorkflowJointConditionPojo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @date 2021/05/21 14:35
 */
@Service("workflowNodeConditionSettings")
public class WorkflowNodeConditionSettings extends AbstractWorkflowNodeSettings {


    private static final String CONTENT = "constant.ConditionNodePojo.content";

    private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowNodeConditionSettings.class);

    @Resource
    private Map<Integer, ConditionNodeFieldService> conditionNodeFieldMap;
    @Resource
    @Lazy
    private WorkflowNodeHelp workflowNodeHelp;

    @Override
    public Integer type() {
        return WorkflowNodeTypeEnum.CONDITION_NODE.getType();
    }

    @Override
    public WorkflowNodeTreePojo getContent(WorkflowNodeEntity workflowNodeEntity, WorkflowGetPojo workflowGetPojo) throws XbbException {
        WorkflowNodeTreePojo workflowNodeTreePojo = new WorkflowNodeTreePojo();
        try {
            ConditionNode conditionNode = workflowNodeHelp.getConditionNode(workflowNodeEntity);

            if (Objects.isNull(conditionNode)) {
                return workflowNodeTreePojo;
            }
            workflowNodeTreePojo.setConditionType(conditionNode.getConditionType());
            workflowNodeTreePojo.setConditionNodeType(conditionNode.getType());
            workflowNodeTreePojo.setPriority(workflowNodeEntity.getPriority());
            if (Objects.equals(ConditionTypeEnum.RESULT_CONDITION.getType(), conditionNode.getType())) {
                // 有结果的条件
                return workflowNodeTreePojo;
            }

            if (Objects.isNull(conditionNode.getConditions())) {
                return workflowNodeTreePojo;
            }

            WorkflowJointConditionPojo conditions = conditionNode.getConditions();

            List<WorkflowConditionFilters> filters = conditions.getFilters();
            String operator = conditions.getOperator();
            WorkflowConditionOperatorEnum workflowConditionOperatorEnum = WorkflowConditionOperatorEnum.getByAlias(operator);

            WorkflowConditionContentFiltersPojo workflowConditionContentFiltersPojo = new WorkflowConditionContentFiltersPojo();
            workflowConditionContentFiltersPojo.setOperator(workflowConditionOperatorEnum.getName());


            List<WorkflowConditionContentFilterPojo> filtersStr = new ArrayList<>();
            for (WorkflowConditionFilters filter : filters) {
                List<WorkflowConditionPojo> conditionPojos = filter.getFilter();
                String filterOperator = filter.getOperator();
                WorkflowConditionOperatorEnum operatorEnum = WorkflowConditionOperatorEnum.getByAlias(filterOperator);

                List<String> attrNameList = new ArrayList<>();
                List<Integer> blockList = Arrays.asList(FieldTypeEnum.CREATOR_DEPT.getType(), FieldTypeEnum.CREATORID.getType(), FieldTypeEnum.ADDTIME.getType(), FieldTypeEnum.UPDATETIME.getType());
                for (WorkflowConditionPojo item : conditionPojos) {
                    Long formId = item.getFormId();
                    Integer businessType = item.getBusinessType();
                    Map<String, FieldAttrEntity> explainMap = WorkflowNodeUtil.getExplainMap(workflowGetPojo, businessType, formId);
                    if (!explainMap.containsKey(item.getAttr()) && !blockList.contains(item.getFieldType())) {
                        continue;
                    }
                    ConditionNodeFieldService conditionNodeFieldService = conditionNodeFieldMap.get(item.getFieldType());
                    String value = conditionNodeFieldService.conditionField(item, workflowGetPojo);
                    attrNameList.add(value);
                }

                WorkflowConditionContentFilterPojo workflowConditionContentFilterPojo = new WorkflowConditionContentFilterPojo();
                workflowConditionContentFilterPojo.setFilter(attrNameList);
                workflowConditionContentFilterPojo.setOperator(operatorEnum.getName());

                filtersStr.add(workflowConditionContentFilterPojo);
            }


            workflowConditionContentFiltersPojo.setFilters(filtersStr);


            workflowNodeTreePojo.setContent(workflowConditionContentFiltersPojo);
        } catch (Exception e) {
            LOGGER.error("WorkflowNodeConditionSettings.getContent error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowNodeTreePojo;
    }



    @Override
    public WorkflowNodeGetVO get(WorkflowNodeEntity workflowNodeEntity) throws XbbException {
        try {
            ConditionNode conditionNode = workflowNodeHelp.getConditionNode(workflowNodeEntity);
            NodeCoreConfigurationPojo nodeCoreConfigurationPojo = new NodeCoreConfigurationPojo();
            ConditionNodeVO conditionNodeVO = getConditions(workflowNodeEntity, conditionNode);
            nodeCoreConfigurationPojo.setConditionNode(conditionNodeVO);
            return new WorkflowNodeGetVO(workflowNodeEntity.getAppId(), workflowNodeEntity.getFormId(), workflowNodeEntity.getMenuId(), workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(),
                    workflowNodeEntity.getUid(), workflowNodeEntity.getId(), workflowNodeEntity.getPrevId(), workflowNodeEntity.getWrapperId(), nodeCoreConfigurationPojo);
        } catch (Exception e) {
            LOGGER.error("WorkflowNodeConditionSettings.get error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private ConditionNodeVO getConditions(WorkflowNodeEntity workflowNodeEntity, ConditionNode conditionNode) throws XbbException {
        ConditionNodeVO conditionNodeVO = new ConditionNodeVO();
        conditionNodeVO.setType(conditionNode.getType());
        conditionNodeVO.setConditionType(conditionNode.getConditionType());
        conditionNodeVO.setEditedData(conditionNode.getEditedData());
        WorkflowGetPojo workflowGetPojo = workflowNodeHelp.getContent(Collections.singletonList(workflowNodeEntity), workflowNodeEntity.getCorpid());

        WorkflowConditionFiltersPojoVO conditionsVO = new WorkflowConditionFiltersPojoVO();

        WorkflowJointConditionPojo conditions = conditionNode.getConditions();

        if (!Objects.isNull(conditions)) {
            conditionsVO.setOperator(conditions.getOperator());
            List<WorkflowConditionFilters> filters = conditions.getFilters();

            List<WorkflowConditionFilterPojoVO> filtersVO = new ArrayList<>();
            for (WorkflowConditionFilters filter : filters) {
                WorkflowConditionFilterPojoVO workflowConditionFilterPojoVO = new WorkflowConditionFilterPojoVO();
                workflowConditionFilterPojoVO.setOperator(filter.getOperator());


                List<WorkflowConditionPojoVO> conditionPojoVOList = new ArrayList<>();
                List<WorkflowConditionPojo> conditionPojos = filter.getFilter();
                if (CollectionsUtil.isNotEmpty(conditionPojos)) {
                    for (WorkflowConditionPojo item : conditionPojos) {
                        Map<String, FieldAttrEntity> explainMap = WorkflowNodeUtil.getExplainMap(workflowGetPojo, item.getBusinessType(), item.getFormId());
                        Integer fieldType = item.getFieldType();
                        String dateType = null;
                        if (explainMap.containsKey(item.getAttr())) {
                            fieldType = explainMap.get(item.getAttr()).getFieldType();
                            dateType = explainMap.get(item.getAttr()).getDateType();
                        }
                        //阶段字段的fieldType有改变，从表单解释里面实时拿
                        if (Objects.equals(fieldType, FieldTypeEnum.STAGE_THRUSTER.getType())) {
                            transferStageCondition(item);
                        }
                        WorkflowConditionPojoVO workflowConditionPojoVO = new WorkflowConditionPojoVO( item.getName(), fieldType, item.getAttr(), item.getTriggerNodeFlag(), item.getWorkflowNodeId(), item.getFormId(), item.getSaasMark(),
                                item.getBusinessType(), item.getSymbol(), item.getTargetWorkflowNodeId(), item.getTargetFormId(), item.getTargetSaasMark(), item.getTargetBusinessType(), item.getValueType(),
                                item.getTargetFieldType(), item.getTargetAttr(), item.getValue());

                        if (Objects.equals(FieldTypeEnum.CREATOR_DEPT.getAlias(), item.getAttr())) {
                            workflowConditionPojoVO.setName(I18nMessageUtil.getMessage(I18nStringConstant.SPONSOR_DEPARTMENT));
                        } else if (!explainMap.containsKey(item.getAttr())) {
                            workflowConditionPojoVO.setDelete(1);
                        } else if (explainMap.containsKey(item.getAttr())){
                            String name = explainMap.get(item.getAttr()).getAttrName();
                            workflowConditionPojoVO.setName(name);
                        }
                        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
                        List<ConditionClass> conditionList = ConditionListHelp.getConditionList(fieldTypeEnum, 0);
                        workflowConditionPojoVO.setWhereList(conditionList);
                        workflowConditionPojoVO.setDateType(dateType);
                        conditionPojoVOList.add(workflowConditionPojoVO);
                    }
                }
                workflowConditionFilterPojoVO.setFilter(conditionPojoVOList);

                filtersVO.add(workflowConditionFilterPojoVO);
            }
            conditionsVO.setFilters(filtersVO);
        } else {
            conditionsVO.setOperator(WorkflowConditionOperatorEnum.OR.getAlias());
            conditionsVO.setFilters(new ArrayList<>());
        }

        conditionNodeVO.setConditions(conditionsVO);
        return conditionNodeVO;
    }

    /**
     * 工作流流转条件历史数据中客户线索机会阶段的code需要由数字转为字符串
     * @param item
     */
    private void transferStageCondition(WorkflowConditionPojo item) {
        List<Object> stageValue = item.getValue();
        if (CollectionsUtil.isNotEmpty(stageValue)) {
            for (int i = 0; i < stageValue.size(); i++) {
                stageValue.set(i, String.valueOf(stageValue.get(i)));
            }
            item.setValue(stageValue);
        }
    }

    @Override
    public WorkflowEnableVO check(WorkflowNodeEntity workflowNodeEntity, Map<Long, WorkflowNodeEntity> nodeMap, WorkflowGetPojo workflowGetPojo) throws XbbException {
        WorkflowEnableVO workflowEnableVO = new WorkflowEnableVO();
        ConditionNode conditionNode = workflowNodeHelp.getConditionNode(workflowNodeEntity);
        if (Objects.equals(workflowNodeEntity.getTriggerType(), WorkflowTriggerMethodEnum.FORM.getType())) {
            if (Objects.equals(conditionNode.getConditionType(), WorkflowNodeConditionTypeEnum.NORMAL_TYPE.getType())) {

                if (Objects.nonNull(conditionNode.getConditions())) {
                    WorkflowJointConditionPojo conditions = conditionNode.getConditions();
                    List<WorkflowConditionFilters> filters = conditions.getFilters();

                    if (CollectionsUtil.isNotEmpty(filters)) {
                        for (WorkflowConditionFilters filter : filters) {
                            List<WorkflowConditionPojo> filterFilter = filter.getFilter();
                            if (CollectionsUtil.isNotEmpty(filterFilter)) {
                                for (WorkflowConditionPojo item : filterFilter) {
                                    if (nodeMap.containsKey(item.getWorkflowNodeId())
                                            && !equals(item.getFormId(), item.getBusinessType(), nodeMap.get(item.getWorkflowNodeId()).getFormId(), nodeMap.get(item.getWorkflowNodeId()).getBusinessType())) {
                                        workflowEnableVO.setSuccess(0);
                                        workflowEnableVO.setWorkflowNodeId(workflowNodeEntity.getId());
                                        return workflowEnableVO;
                                    }
                                    if (nodeMap.containsKey(item.getTargetWorkflowNodeId())
                                            && !equals(item.getTargetFormId(), item.getTargetBusinessType(), nodeMap.get(item.getTargetWorkflowNodeId()).getFormId(),
                                            nodeMap.get(item.getTargetWorkflowNodeId()).getBusinessType())) {
                                        workflowEnableVO.setSuccess(0);
                                        workflowEnableVO.setWorkflowNodeId(workflowNodeEntity.getId());
                                        return workflowEnableVO;
                                    }
                                    if (Objects.isNull(item.getValue()) && !Objects.equals(ConditionEnum.EMPTY.getSymbol(), item.getSymbol()) && !Objects.equals(ConditionEnum.NOEMPTY.getSymbol(), item.getSymbol())) {
                                        workflowEnableVO.setSuccess(0);
                                        workflowEnableVO.setWorkflowNodeId(workflowNodeEntity.getId());
                                        workflowEnableVO.setMessage(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_CONDITION_VALUE_NOT_EMPTY));
                                        return workflowEnableVO;
                                    }

                                }
                            }
                        }

                    }

                }
            }
        }
        return workflowEnableVO;
    }

    @Override
    public void replaceWorkflowNodeId(WorkflowNodeEntityExt workflowNodeEntityExt, Map<Long, Long> workflowNodeMap) throws XbbException {
        //兼容老数据
        WorkflowJointConditionPojo newConditions = workflowNodeHelp.getConditionNode(workflowNodeEntityExt).getConditions();
        JSONObject config = JSONObject.parseObject(workflowNodeEntityExt.getConfigData());
        config.put("conditions", newConditions);
        workflowNodeEntityExt.setConfigData(config.toJSONString());
        ConditionNode conditionNode = JSON.parseObject(workflowNodeEntityExt.getConfigData(), ConditionNode.class);

        if (Objects.nonNull(conditionNode) && Objects.nonNull(conditionNode.getConditions())) {
            WorkflowJointConditionPojo conditions = conditionNode.getConditions();
            if (Objects.nonNull(conditions)) {
                List<WorkflowConditionFilters> filters = conditions.getFilters();
                if (CollectionsUtil.isNotEmpty(filters)) {
                    for (WorkflowConditionFilters filter : filters) {
                        List<WorkflowConditionPojo> filterFilter = filter.getFilter();
                        if (CollectionsUtil.isNotEmpty(filterFilter)) {
                            filterFilter.forEach(item->{
                                item.setWorkflowNodeId(workflowNodeMap.get(item.getWorkflowNodeId()));
                            });

                        }
                    }

                }
            }
            workflowNodeEntityExt.setConfigData(JSON.toJSONString(conditionNode));
        }
    }
}

